home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 May / macformat-024.iso / Shareware City / Developers / nshellmegasource1.50 / mega src / commands / du.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-26  |  8.8 KB  |  387 lines  |  [TEXT/KAHL]

  1. /* ========== the commmand file: ==========
  2.  
  3.     du.c
  4.     
  5.     Copyright (c) 1994 Newport Software Development
  6.     
  7.     You may distribute unmodified copies of this file for
  8.     noncommercial purposes.  You may use this file as a
  9.     reference when writing your own nShell(tm) commands.
  10.     
  11.     All other rights are reserved.
  12.     
  13.    ========== the commmand file: ========== */
  14.  
  15. #ifdef __MWERKS__            // Get the appropriate A4 stuff
  16. #include <A4Stuff.h>
  17. #else
  18. #include <SetUpA4.h>
  19. #endif
  20.  
  21. #include "nshc.h"
  22. #include "walk_utl.h"
  23.  
  24. #include "arg_utl.proto.h"
  25. #include "buf_utl.proto.h"
  26. #include "nshc_utl.proto.h"
  27. #include "str_utl.proto.h"
  28. #include "fss_utl.proto.h"
  29. #include "walk_utl.proto.h"
  30.  
  31. /* ======================================== */
  32.  
  33. // define the walking states
  34.  
  35. typedef enum { ws_none, ws_init, ws_next } t_walks;
  36.  
  37. // data definition - this struct is the root of all data
  38.  
  39. typedef struct {
  40.  
  41.     short        arg;                        // position in arg list
  42.     t_walks        walk_state;                    // interal walk state
  43.     
  44.     short        show_all;                    // 1 when -a option present
  45.     short        summary_only;                // 1 when -s option present
  46.     
  47.     Str32        names[MAX_WALK_LEVELS];        // the path being processed
  48.     long        totals[MAX_WALK_LEVELS];    // the totals being calculated
  49.     
  50.     short        old_level;                    // monitor when we pop up a level
  51.     short        old_dir;                    // 1 if last item was a dir
  52.     Str32        old_name;                    // name of last item
  53.     
  54.     t_walk_hndl    wData;                        // storage for the walk structure
  55.  
  56. } t_du_data;
  57.  
  58. typedef    t_du_data    **t_du_hndl;
  59.  
  60. /* ======================================== */
  61.  
  62. // local prototypes
  63.  
  64. OSErr du_start( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls );
  65. OSErr du_continue( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls );
  66. OSErr du_stop( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls );
  67. void  du_shift_args( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, short arg );
  68. OSErr du_init( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_du_hndl duData );
  69. OSErr du_next( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_du_hndl duData );
  70. OSErr du_size_of( FSSpec *spec, long *size );
  71. void  du_report_level( t_nshc_calls *nshc_calls, t_du_hndl duData, long size,  short level, Str32 name );
  72.  
  73. /* ======================================== */
  74.  
  75. void du_shift_args( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, short arg )
  76. {
  77.     short        new_arg;
  78.  
  79.     new_arg = arg + 1;
  80.     
  81.     while ( new_arg < nshc_parms->argc ) {
  82.         nshc_parms->argv[ arg ] = nshc_parms->argv[ new_arg ];
  83.         arg++;
  84.         new_arg++;
  85.         }
  86.         
  87.     nshc_parms->argc--;
  88. }
  89.  
  90. /* ======================================== */
  91.  
  92. OSErr du_init( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_du_hndl duData )
  93. {
  94.     OSErr        result;
  95.     FSSpec        fss;
  96.     t_walk_hndl wData;
  97.     Str255        path;
  98.     
  99.     if ( ( (**duData).arg > 1 ) && ( (**duData).arg >= nshc_parms->argc ) ) {
  100.         nshc_parms->action = nsh_stop;
  101.         return( 0 );
  102.         }
  103.     
  104.     if ( nshc_parms->argc > 1 )
  105.         result = arg_to_real_fss( nshc_parms, nshc_calls, (**duData).arg, &fss );
  106.     else {
  107.         pStrCopy( path, "\p:" );
  108.         result = nshc_calls->NSH_path_expand( path );
  109.         if ( !result )
  110.             result = nshc_calls->NSH_path_to_FSSpec( path, &fss );
  111.         }
  112.  
  113.     (**duData).arg++;
  114.     
  115.     if (result) {
  116.         nshc_parms->action = nsh_stop;
  117.         return( -1 );
  118.         }
  119.     
  120.     wData = walk_init( &fss );
  121.     
  122.     if ( !wData ) {
  123.         nshc_calls->NSH_putStr_err( "\pdu: Could not init Walk Library.\r" );
  124.         nshc_parms->action = nsh_stop;
  125.         return( -1 );
  126.         }
  127.  
  128.     if ( (**duData).arg > 2 )
  129.         buf_putchar( '\r' );        // put a blank line between sets of data
  130.  
  131.     (**duData).wData = wData;
  132.     (**duData).walk_state = ws_next;
  133.     (**duData).old_level = 0;
  134.     (**duData).old_dir = 0;
  135.     (**duData).old_name[0] = 0;
  136. }
  137.  
  138. /* ======================================== */
  139.  
  140. OSErr du_next( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_du_hndl duData )
  141. {
  142.     short        i;
  143.     long        size;
  144.     short        level;
  145.     short        isDir;
  146.     FSSpec        fss;
  147.     OSErr        error;
  148.     t_walk_hndl wData;
  149.     FInfo        fndrInfo;
  150.     
  151.     wData = (**duData).wData;
  152.     
  153.     if ( !wData ) {
  154.         nshc_calls->NSH_putStr_err( "\pdu: Missing data.\r" );
  155.         nshc_parms->action = nsh_stop;
  156.         return( -1 );
  157.         }
  158.  
  159.     error = walk_next( wData, &fss, &level, &isDir );
  160.     
  161.     if ( ( level <= (**duData).old_level ) && (**duData).old_dir )
  162.         du_report_level( nshc_calls, duData, 0L, (**duData).old_level, (**duData).old_name );
  163.  
  164.     if ( level < (**duData).old_level )
  165.         for ( i = (**duData).old_level ; i > level ; i-- ) {
  166.             size = (**duData).totals[i];
  167.             (**duData).totals[i] = 0L;
  168.             du_report_level( nshc_calls, duData, size, i, 0L );
  169.             (**duData).totals[i - 1] += size;
  170.             }
  171.             
  172.     if (error) {
  173.         (**duData).walk_state = ws_init;
  174.         DisposeHandle( wData );
  175.         (**duData).wData = 0L;
  176.         (**duData).old_level = 0;
  177.         return(0);
  178.         }
  179.         
  180.     if ( level > (**duData).old_level )
  181.         for ( i = 1 ; i <= level ; i++ )
  182.             pStrCopy( (**duData).names[i], (**wData).levels[i].fss.name );
  183.  
  184.     (**duData).old_level = level;
  185.     (**duData).old_dir = isDir;
  186.     pStrCopy( (**duData).old_name, fss.name );
  187.     
  188.     if (isDir)
  189.         return( 0 );
  190.  
  191.     error = du_size_of( &fss, &size );
  192.  
  193.     if ( error ) {
  194.         nshc_calls->NSH_putStr_err( "\pdu: Could not read file size.\r" );
  195.         nshc_parms->action = nsh_stop;
  196.         return( -1 );
  197.         }
  198.     
  199.     (**duData).totals[level] += size;
  200.     
  201.     if ( (**duData).show_all )
  202.         du_report_level( nshc_calls, duData, size, level, fss.name );
  203.  
  204.     return(0);
  205. }
  206.  
  207. /* ========================================== */
  208.  
  209. void du_report_level( t_nshc_calls *nshc_calls,
  210.                       t_du_hndl duData,
  211.                       long size,
  212.                       short level,
  213.                       Str32 name )
  214. {
  215.     short    i;
  216.     Str32    temp_str;
  217.     
  218.     if ( (**duData).summary_only && ( ( level > 1 ) || name ) )
  219.         return;
  220.     
  221.     NumToString( ( size + 512 ) / 1024, temp_str );
  222.     i = 7 - temp_str[0];
  223.     while (i--) buf_putchar( ' ' );
  224.     buf_putStr( temp_str );
  225.     buf_putchar( ' ' );
  226.  
  227.     for ( i = 1 ; i <= level; i++ ) {
  228.         buf_putStr( (**duData).names[i] );
  229.         buf_putchar( ':' );
  230.         }
  231.     
  232.     if ( name )
  233.         buf_putStr( name );
  234.         
  235.     buf_putchar( '\r' );
  236. }
  237.  
  238. /* ========================================== */
  239.  
  240. OSErr du_size_of( FSSpec *spec, long *size )
  241. {
  242.     CInfoPBRec pb;
  243.     OSErr error;
  244.  
  245.     pb.hFileInfo.ioNamePtr = (StringPtr)spec->name;
  246.     pb.hFileInfo.ioVRefNum = spec->vRefNum;
  247.     pb.hFileInfo.ioDirID = spec->parID;
  248.     pb.hFileInfo.ioFDirIndex = 0;
  249.     error = PBGetCatInfoSync(&pb);
  250.     
  251.     if ( error || (pb.hFileInfo.ioFlAttrib & 16) )    // if is a dir, return 0
  252.         *size = 0;
  253.     else
  254.         *size = pb.hFileInfo.ioFlPyLen + pb.hFileInfo.ioFlRPyLen;
  255.     
  256.     return (error);
  257. }
  258.  
  259. /* ======================================== */
  260.  
  261. OSErr du_start( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls )
  262. {
  263.     short        arg;
  264.     t_du_hndl    duData;
  265.  
  266.     // get data space
  267.  
  268.     duData = (t_du_hndl)NewHandleClear( sizeof( t_du_data ) );
  269.  
  270.     if (!duData) {
  271.         nshc_calls->NSH_putStr_err( "\pdu: Could not allocate data.\r" );
  272.         nshc_parms->action = nsh_stop;
  273.         return( -1 );
  274.         }
  275.     
  276.     nshc_parms->data = (Handle)duData;
  277.     
  278.     // set defaults
  279.     
  280.     (**duData).arg = 1;                            // start at the arg = 1 position
  281.     (**duData).walk_state = ws_init;            // start by initing a searchrule_
  282.  
  283.     // set up options
  284.             
  285.     (**duData).show_all = nshc_got_option( nshc_parms, 'a' );
  286.     
  287.     (**duData).summary_only = nshc_got_option( nshc_parms, 's' );
  288.     
  289.     // and remove options from parameter list
  290.  
  291.     if ( arg = nshc_got_option( nshc_parms, 'a' ) )
  292.         du_shift_args( nshc_parms, nshc_calls, arg );
  293.         
  294.     if ( arg = nshc_got_option( nshc_parms, 's' ) )
  295.         du_shift_args( nshc_parms, nshc_calls, arg );
  296.         
  297.     // and continue
  298.     
  299.     nshc_parms->action = nsh_continue;
  300. }
  301.  
  302. /* ======================================== */
  303.  
  304. OSErr du_continue( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls )
  305. {
  306.     OSErr        result;
  307.     t_du_hndl duData;
  308.  
  309.     duData = (t_du_hndl)nshc_parms->data;
  310.  
  311.     if ( !duData ) {
  312.         nshc_calls->NSH_putStr_err( "\pdu: Missing data.\r" );
  313.         nshc_parms->action = nsh_stop;
  314.         return( -1 );
  315.         }
  316.  
  317.     if ( (**duData).walk_state == ws_init )
  318.         result = du_init( nshc_parms, nshc_calls, duData );
  319.     else
  320.         result = du_next( nshc_parms, nshc_calls, duData );
  321.         
  322.     return( result );
  323. }
  324.  
  325. /* ======================================== */
  326.  
  327. OSErr du_stop( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls )
  328. {
  329.     t_du_hndl duData;
  330.     t_walk_hndl wData;
  331.  
  332.     duData = (t_du_hndl)nshc_parms->data;
  333.     wData = (**duData).wData;
  334.  
  335.     if (duData)
  336.         DisposeHandle( duData );
  337.  
  338.     if (wData)
  339.         DisposeHandle( wData );
  340.  
  341.     nshc_parms->action = nsh_idle;
  342. }
  343.  
  344. /* ======================================== */
  345.  
  346. void main(t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls)
  347. {
  348. #ifdef __MWERKS__
  349.     long oldA4  = SetCurrentA4();
  350. #else
  351.     RememberA0();
  352.     SetUpA4();
  353. #endif
  354.  
  355.     buf_init( nshc_calls );
  356.     
  357.     if (!nshc_bad_version( nshc_parms, nshc_calls, NSHC_VERSION )) {
  358.     
  359.          // otherwise, handle requests from the application
  360.     
  361.           switch (nshc_parms->action) {
  362.             case nsh_start:
  363.                 nshc_parms->result = du_start( nshc_parms, nshc_calls );
  364.                 break;
  365.             case nsh_continue:
  366.                 nshc_parms->result = du_continue( nshc_parms, nshc_calls );
  367.                 break;
  368.             case nsh_stop:
  369.                 nshc_parms->result = du_stop( nshc_parms, nshc_calls );
  370.                 break;
  371.             default:
  372.                 nshc_parms->result = NSHC_NO_ERR;
  373.                 nshc_parms->action = nsh_idle;
  374.                 break;
  375.             }
  376.         
  377.         }
  378.         
  379.     buf_flush();
  380.     
  381. #ifdef __MWERKS__
  382.     SetA4(oldA4);
  383. #else
  384.     RestoreA4();
  385. #endif
  386. }
  387.